package com.ruslan.magaz.repository;


import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.ruslan.magaz.domain.Category;
import com.ruslan.magaz.domain.OrderStatus;
import com.ruslan.magaz.domain.Product;
import com.ruslan.magaz.domain.Rating;
import com.ruslan.magaz.domain.User;

@Repository
public class ItemDaoImpl implements ItemDao{

	@Autowired
	private SessionFactory sessionFactory;


	@Override
	public Product getProductById(int id) {
		return (Product) sessionFactory.getCurrentSession().get(Product.class, id);
	}

	@Override
	public List<Category> getAllCategories() {
		Query query = sessionFactory.getCurrentSession().createQuery("FROM Category");
		return  (List<Category>) query.list();
	}

	@Override
	public List<Category> getAllCategories(int pageNum, int pageSize) {
		Query query = sessionFactory.getCurrentSession().createQuery("FROM Category");
		query.setFirstResult((pageNum - 1) * pageSize);
		query.setMaxResults(pageSize);
		return  (List<Category>) query.list();
	}
	
	@Override
	public List<String> getCategoryNames() {
		Query query = sessionFactory.getCurrentSession().createQuery("SELECT c.name from Category c");
		return  (List<String>) query.list();
	}
	
	@Override
	public Integer getFirstCategoryId() {
		  Query query = sessionFactory.getCurrentSession().createQuery("SELECT min(c.categoryId) FROM Category c");
		  return  (Integer) query.uniqueResult();
	}

	@Override
	public int categoriesPageCount(int pageSize) {
		Query query = sessionFactory.getCurrentSession().createQuery("Select count (c.id) FROM Category c");
		return (((Long)query.uniqueResult()).intValue()/pageSize)+1;
	}

	@Override
	public List<Product> getAllProductsForCategory(int categoryId, int pageNum, int pageSize) {
		Query query = sessionFactory.getCurrentSession().createQuery("FROM Product WHERE Category_id = :id");
		query.setInteger("id", categoryId);
		query.setFirstResult((pageNum - 1) * pageSize);
		query.setMaxResults(pageSize);
		return  (List<Product>) query.list();
	}
	@Override
	public int productsForCategoryPageCount(int categoryId, int pageSize) {
		Query query = sessionFactory.getCurrentSession().createQuery("Select count (p.id) FROM Product p WHERE Category_id = :id");
		query.setInteger("id", categoryId);
		return (((Long)query.uniqueResult()).intValue()/pageSize)+1;
	}
	
	@Override
	public List<Rating> getAllReviewsForProduct(int productId, int pageNum, int pageSize) {
		Query query = sessionFactory.getCurrentSession().createQuery("FROM Rating WHERE Product_id = :id AND ReviewText!='' AND ReviewText is not NULL");
		query.setInteger("id", productId);
		query.setFirstResult((pageNum - 1) * pageSize);
		query.setMaxResults(pageSize);
		return  (List<Rating>) query.list();
	}
	@Override
	public int reviewsForProductPageCount(int productId, int pageSize) {
		Query query = sessionFactory.getCurrentSession().createQuery("Select count (r.id) FROM Rating r WHERE Product_id = :id AND ReviewText!='' AND ReviewText is not NULL");
		query.setInteger("id", productId);
		return (((Long)query.uniqueResult()).intValue()/pageSize)+1;
	}
	
	@Override
	public double getAvgRating(int productId){
		Query query = sessionFactory.getCurrentSession().createQuery("select AVG(r.mark) FROM Rating r WHERE Product_id = :id");
		query.setInteger("id", productId);
		Double mark = (Double) query.uniqueResult();
		if (mark == null){
			return 0;
		}else{
			return (Double) query.uniqueResult();
		}
	}
	
	@Override
	public int countRaters(int productId){
		Query query = sessionFactory.getCurrentSession().createQuery("select COUNT(r.mark) FROM Rating r WHERE Product_id = :id");
		query.setInteger("id", productId);
		return ((Long) query.uniqueResult()).intValue();
	}


	@Override
	public Rating getRatingForUserNItem(int userId, int itemId) {
		Query query = sessionFactory.getCurrentSession().createQuery("FROM Rating WHERE Product_id = :itemId AND User_id = :userId");
		query.setInteger("itemId", itemId);
		query.setInteger("userId", userId);
		return (Rating) query.uniqueResult();
	}


	@Override
	public void editRating(Rating rating) {
		Session session = sessionFactory.getCurrentSession();
		Rating existingRating = (Rating) session.get(Rating.class, rating.getRatingId());
		existingRating.setMark(rating.getMark());
		existingRating.setReviewText(rating.getReviewText());
	}




	@Override
	public void addRating(Rating rating) {
		Session session = sessionFactory.getCurrentSession();
		session.save(rating);
	}


	@Override
	public int getCountForProductId(int productId) {
		Query query = sessionFactory.getCurrentSession().createQuery("SELECT p.stock FROM Product p WHERE Product_id = :productId");
		query.setInteger("productId", productId);
		return (Integer) query.uniqueResult();
	}

	@Override
	public void moveProductsFromCategory(int fromId, int toId) {
		Session session = sessionFactory.getCurrentSession();
		Query query = session.createQuery("FROM Product WHERE Category_id = :id");
		query.setInteger("id", fromId);
		Category newCategory = (Category) session.get(Category.class, toId);
		List<Product> productList = (List<Product>) query.list();
		for (Product product:productList){
			product.setCategory(newCategory);
		}
	}
	
	@Override
	public int countItemsInCategory(int categoryId) {
		Session session = sessionFactory.getCurrentSession();
		Query query = session.createQuery("Select count (p.productId) FROM Product p WHERE Category_id = :id");
		query.setInteger("id", categoryId);
		return ((Long)query.uniqueResult()).intValue();
	}

	@Override
	public void addCategory(Category category) {
		Session session = sessionFactory.getCurrentSession();
		session.save(category);
		
	}

	@Override
	public void removeCategory(int categoryId) {
		Session session = sessionFactory.getCurrentSession();
		Category category = (Category) session.get(Category.class, categoryId);
		session.delete(category);
		
	}

	@Override
	public Category getCategoryByName(String name) {
		Session session = sessionFactory.getCurrentSession();
		Query query = session.createQuery("FROM Category c WHERE name = :name");
		query.setString("name", name);
		return (Category) query.uniqueResult();
	}

	@Override
	public void editProduct(Product product) {
		Session session = sessionFactory.getCurrentSession();
		Product existingProduct = (Product) session.get(Product.class, product.getProductId());
		existingProduct.setActualPrice(product.getActualPrice());
		existingProduct.setStock(product.getStock());
	}
	
	@Override
	public void deepEditProduct(Product product) {
		Session session = sessionFactory.getCurrentSession();
		Product existingProduct = (Product) session.get(Product.class, product.getProductId());
		existingProduct.setActualPrice(product.getActualPrice());
		existingProduct.setStock(product.getStock());
		existingProduct.setDescription(product.getDescription());
		existingProduct.setDescription(product.getDescription());
		existingProduct.setName(product.getName());
		existingProduct.setCategory(product.getCategory());
	}

	@Override
	public void addProduct(Product product) {
		Session session = sessionFactory.getCurrentSession();
		session.save(product);
	}

	@Override
	public void editCategory(Category category) {
		Session session = sessionFactory.getCurrentSession();
		Category existingCategory = (Category) session.get(Category.class, category.getCategoryId());
		existingCategory.setName(category.getName());
		
	}

	@Override
	public Category getCategoryById(int categoryId) {
		Session session = sessionFactory.getCurrentSession();
		return (Category) session.get(Category.class, categoryId);
	}

}
